import {USER_ROLE, USER_STATUS} from '#src/constants/user.constants.js';
import {ResponseHandler} from '#src/common/utils/http/responseHandler.js';
import {User} from '#src/models/User.js';
import jwtService from '#src/common/services/auth/JwtService.js';
import {handleServiceError} from '#src/common/utils/serviceHelper.js';
import {verifyPassword} from "#src/common/utils/password.util.js";
import {UserMessage} from "#src/constants/message.constants.js";
import {UserRepository} from '#src/module/user/repository/UserRepository.js';
import {NotFoundError} from '#src/common/errors/index.js';
import {AuthenticationError, ConflictError, ForbiddenError} from '#src/common/errors/index.js';
import {UserRegisterResponseDTO, UserLoginResponseDTO} from '#src/module/user/dto/response/user.js';

/**
 * 用户服务类，处理用户相关的业务逻辑
 * 包括用户注册、登录、信息查询等核心功能
 * @class UserService
 * @module UserModule
 */
export class UserService {
    /**
     * 创建UserService实例并初始化用户仓库依赖
     * @constructor
     */
    constructor() {
        this.userRepository = new UserRepository();
    }

    /**
     * 根据用户ID查询用户信息
     * @async
     * @param {string} userId - 用户唯一标识符
     * @returns {Promise<User>} - 返回用户对象
     * @throws {NotFoundError} - 当用户不存在时抛出
     */
    async getUser(userId) {
        return handleServiceError(async () => {
            const user = await this.userRepository.findById(userId);
            if (!user) {
                throw new NotFoundError('User not found');
            }
            return user;
        }, 'UserService.getUser', {userId});
    }

    /**
     * 用户注册服务
     * @async
     * @param {Request} req - Express请求对象，包含验证后的注册数据
     * @returns {Promise<UserRegisterResponseDTO>} - 注册结果DTO
     * @throws {ConflictError} - 当邮箱已存在时抛出
     * @description 处理用户注册流程：验证邮箱唯一性、生成用户ID、设置默认状态、创建用户及关联角色
     */
    async register(req) {
        return handleServiceError(async () => {
            const registerDTO = req.validatedData;  // 使用请求验证后的数据

            // 检查邮箱是否已注册
            const exists = await this.userRepository.findByEmail(registerDTO.email);
            if (exists) {
                throw new ConflictError(UserMessage.EMAIL_EXISTS);
            }

            // 构建新用户对象
            const newUser = {
                ...registerDTO,
                id: User.generateUUID(),  // 生成UUID作为用户ID
                status: USER_STATUS.ACTIVE,  // 设置默认状态为活跃
                created_at: new Date().toISOString().slice(0, 19).replace('T', ' '),
                updated_at: new Date().toISOString().slice(0, 19).replace('T', ' ')
            };

            // 创建用户并分配默认角色(普通用户)
            const result = await this.userRepository.createUserWithRole(newUser, USER_ROLE.USER);

            // 使用DTO格式化响应数据
            return UserRegisterResponseDTO.fromServiceResponse({
                userId: result.insertId,
                message: UserMessage.REGISTER_SUCCESS
            });
        }, 'UserService.register', {email: req.validatedData.email});
    }

    /**
     * 用户登录服务
     * @async
     * @param {Object} credentials - 用户登录凭证
     * @param {string} credentials.email - 用户邮箱
     * @param {string} credentials.password - 用户密码
     * @returns {Promise<Response>} - 包含JWT令牌和用户信息的响应
     * @throws {AuthenticationError} - 当邮箱不存在或密码验证失败时抛出
     * @description 处理用户认证流程：验证用户存在性、密码比对、生成JWT令牌、构建登录响应
     */
    async login(credentials) {
        return handleServiceError(async () => {
            // 1. 根据邮箱查询用户
            const user = await this.userRepository.findByEmail(credentials.email);
            if (!user) {
                throw new AuthenticationError(UserMessage.INVALID_CREDENTIALS);
            }

            // 2. 验证密码
            const isPasswordValid = await verifyPassword(
                user,  // 用户对象(包含加密密码)
                credentials.password  // 明文密码
            );
            if (!isPasswordValid) {
                throw new AuthenticationError(UserMessage.INVALID_CREDENTIALS);
            }

            // 3. 获取用户角色
            const roles = await this.userRepository.getUserRoles(user.id);

            // 4. 生成JWT令牌
            const token = jwtService.generateToken({
                id: user.id,
                email: user.email,
                username: user.username,
                roles: roles.map(role => role.code)
            });

            // 5. 使用DTO和ResponseHandler构建标准响应
            return ResponseHandler.success(
                UserLoginResponseDTO.fromServiceResponse({
                    token,
                    user: {
                        id: user.id,
                        username: user.username,
                        email: user.email,
                        roles: roles.map(role => role.name),
                        status: user.status
                    }
                })
            );
        }, 'UserService.login', credentials);
    }
}